package com.yunzhu.yunzhubookingservice.exception;

import com.yunzhu.yunzhubookingservice.model.sys.AjaxResponse;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;

/**
 * 设计数据结构：
 * 1.CustomException 自定义异常。核心要素：异常错误编码（200，400，500），异常错误信息message
 * 2.ExceptionTypeEnum 枚举异常分类，将异常分类固化下来，防止开发人员思维发散，核心要素：异常分类编码（200，400，500），异常分类描述
 * 3.AjaxResponse 用于响应Ajax请求，核心要素：是否请求成功isok，响应code（200，400，500），响应描述message，响应成功的数据data
 * 4.error.jsp 全局统一异常处器，转换异常到统一响应数据理，并统一跳转404页面
 * 全局异常处理器一般只拦截自定义异常，
 */
@ControllerAdvice //@ControllerAdvice注解表明当前类是一个全局的异常处理类
public class WebExceptionHandler {
    @ExceptionHandler(CustomException.class) //@ExceptionHandler(CustomException.class)表示针对CustomException要做customerException()方法处理
    @ResponseBody
    public AjaxResponse customerException(CustomException e){
        if(e.getCode() == CustomExceptionType.SYSTEM_ERROR.getCode()){
            //TODO 将500异常信息持久化处理，方便运维人员处理，400信息则直接返回告知用户就行
        }
        return AjaxResponse.error(e); //把自定义异常转为统一响应数据结构，并返回给前端
    }

    //数据校验注解会产生两种异常MethodArgumentNotValidException，BindException
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public AjaxResponse handleBindException(MethodArgumentNotValidException e){
        FieldError fieldError = e.getBindingResult().getFieldError();
        return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,fieldError.getDefaultMessage()));//fieldError.getDefaultMessage()能获取注解使用时自定义的提示信息
    }

    @ExceptionHandler(BindException.class)
    @ResponseBody
    public AjaxResponse handleBindException(BindException e){
        FieldError fieldError = e.getBindingResult().getFieldError();
        return AjaxResponse.error(new CustomException(CustomExceptionType.USER_INPUT_ERROR,fieldError.getDefaultMessage()));
    }

    @ExceptionHandler(ModelViewException.class)
    public ModelAndView viewExceptionHandle(HttpServletRequest req, ModelViewException e){
        ModelAndView modelAndView = new ModelAndView();

        //将异常信息设置，如modelAndView
        modelAndView.addObject("exception",e);
        modelAndView.addObject("url",req.getRequestURL());
        modelAndView.setViewName("error");

        //返回ModelAndView
        return modelAndView;
    }

    @ExceptionHandler(Exception.class)//扩展全局异常处理器的异常处理范围
    @ResponseBody
    public AjaxResponse exception(Exception e){
        //TODO 将异常信息持久化处理，方便运维人员处理

        //没有被开发人员发现，未被转为自定义异常的异常被转为“未知异常”
        return AjaxResponse.error(new CustomException(CustomExceptionType.OTHER_ERROR,"未知异常"));
    }
}
